package com.mm.base.filter.xss;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.mm.util.common.CrosXssFilterConfigUtil;
import com.mm.util.result.DResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * SQL && XSS过滤器
 *
 * @author yl
 */
@Slf4j
@Order(10)
@WebFilter(urlPatterns = "/*", filterName = "CrosXssFilterFilter")
@Component
public class CrosXssFilterFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        ServletResponse response = servletResponse;
        // 如果防注入关闭，则不执行后续校验操作
        if (!CrosXssFilterConfigUtil.getOpenFilterProtect()) {
            filterChain.doFilter(request, response);
        } else {
            XssAndSqlHttpServletRequestWrapper xssRequest = new XssAndSqlHttpServletRequestWrapper(request);
            String method = ((HttpServletRequest) request).getMethod();
            String param = "";
            if ("POST".equalsIgnoreCase(method)) {
                param = this.getBodyString(xssRequest.getReader());
                if (StrUtil.isNotBlank(param)) {
                    if (xssRequest.checkXSSAndSql(param)) {
                        log.error("Api Parameters contain keywords that do not allow sql. {}", request.getRequestURL());
                        DResult result = DResult.failed("Api Parameters contain keywords that do not allow sql.");
                        servletResponse.setCharacterEncoding("UTF-8");
                        servletResponse.setContentType("application/json;charset=UTF-8");
                        PrintWriter out = servletResponse.getWriter();
                        out.write(JSONUtil.toJsonStr(result));
                        return;
                    }
                }
            }
            if (xssRequest.checkParameter()) {
                log.error("Api Parameters contain keywords that do not allow sql. {}", request.getRequestURL());
                DResult result = DResult.failed("Api Parameters contain keywords that do not allow sql.");
                servletResponse.setCharacterEncoding("UTF-8");
                servletResponse.setContentType("application/json;charset=UTF-8");
                PrintWriter out = servletResponse.getWriter();
                out.write(JSONUtil.toJsonStr(result));
                return;
            }
            filterChain.doFilter(xssRequest, servletResponse);
        }
    }


    /**
     * 获取request请求body中参数
     *
     * @param br
     * @return
     */
    public String getBodyString(BufferedReader br) {
        String inputLine;
        String str = "";
        try {
            while ((inputLine = br.readLine()) != null) {
                str += inputLine;
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }

    @Override
    public void destroy() {

    }

}
